<?php
// ------------------------------------------------------------------------
// |@Author       : Jarmin <edshop@qq.com>
// |@----------------------------------------------------------------------
// |@Date         : 2023-06-24 19:33:50
// |@----------------------------------------------------------------------
// |@LastEditTime : 2023-06-24 20:19:08
// |@----------------------------------------------------------------------
// |@LastEditors  : Jarmin <jarmin@ladmin.cn>
// |@----------------------------------------------------------------------
// |@Description  : 
// |@----------------------------------------------------------------------
// |@FilePath     : Role.php
// |@----------------------------------------------------------------------
// |@Copyright (c) 2023 http://www.ladmin.cn   All rights reserved. 
// ------------------------------------------------------------------------
namespace app\setting\logic;

use think\admin\Logic;

/**
 * 角色逻辑类，用于实现角色相关的业务逻辑操作。
 */
class Role extends Logic
{
    /**
     * 根据条件查询角色列表。
     * 如果 $data 中包含 name 字段，则返回名称包含指定字符串的角色列表；
     * 否则返回全部角色列表。角色列表按 sort 字段递增排序。
     * @param array $data 查询条件。可以包含 name 字段，表示查询名称包含指定字符串的角色列表。
     * @return array 角色列表数组。
     */
    public function getList(array $data): array
    {
        // 根据查询条件 $data 组装 SQL 的 WHERE 子句
        $where = !empty($data['name']) ? [["name", "like", "%" . $data['name'] . "%"]] : [["id", ">", 0]];
        // 构建分页参数
        $page = $data['page'] ?? 1;
        $pageSize = $data['pageSize'] ?? 20;
        // 使用关联模型一次性获取所有用户及其所属角色信息
        $roles = $this->modelSystemRole->where($where)->order(['id' => 'desc'])->paginate(['list_rows' => $pageSize, 'page' => $page]);
        // 返回查询结果和执行状态信息
        return $this->json(SUCCESS, lang('role.get_role_list_success'), $roles->toArray());
    }

    /**
     * 获取指定角色的权限列表
     * @param  array $data 查询条件，包含 role_id 字段
     * @return array       菜单 ID 列表
     */
    public function authRole(array $data)
    {
        // 查询指定角色的权限列表和角色信息
        $role = $this->modelSystemRole->with('auth')->field('id, data_type, dept_list, grid_list, dashboard')->find($data['role_id']);
        // 如果查询角色信息成功，则将dept_list、grid_list和dashboard_list解码
       if ($role) {
           $role->dept_list = !empty($role->dept_list) ? json_decode($role->dept_list) : [];
           $role->grid_list = !empty($role->grid_list) ? json_decode($role->grid_list) : [];
       }
       // 组装权限列表和角色信息并返回
       return $this->json(SUCCESS, lang('role.get_role_auth_success'),[
           'auth' => $role->auth ? json_decode($role->auth->menu_id_list) : [],
           'role' => $role ? $role->toArray() : []
       ]);
    }

    /**
     * 保存角色信息。如果 $data 中包含 id，则执行更新操作；否则执行添加操作。
     * @param array $data 角色信息。必须包含 name、sort、status 等字段。
     * @return JsonResponse
     */
    public function saveRole(array $data)
    {
        return $this->tryCatch(function() use ($data){
            if (!empty($data['id'])) {
                // 如果传入的 $data 中有 id ，则执行更新操作
                $this->modelSystemRole->updateById($data['id'], $data);
                // 编辑成功，写入日志
                // $this->serviceSystem->setLog(SUCCESS, 'info', lang('log.role_edit'), lang('log.edit_role_info',['name'=>$data['name']]));
            } else {
                $data['grid_list'] = json_encode(["welcome","ver"]);
                // 否则执行添加操作
                $data['id'] = $this->modelSystemRole->add($data);
                // 创建成功，写入日志
                // $this->serviceSystem->setLog(SUCCESS, 'info', lang('log.role_add'), lang('log.add_role_info',['name'=>$data['name']]));
            }
            // 返回保存结果和角色信息
            return $this->json(SUCCESS, lang('role.save_role_info_success'), $data);
        });
    }

    /**
     * 更新角色状态
     * @param array $data 包含用户 ID 和用户状态值的数组
     * @return array 包含成功码、成功信息和用户信息的 JSON 对象
     */
    public function stateRole(array $data)
    {
        return $this->tryCatch(function() use ($data){
            // 根据 $data 中的 id 值，更新角色状态为 $data 中的 status 值。
            $this->modelSystemRole->updateById($data['id'], $data);
            // 根据用户状态值，设置日志信息
            $status = $data['status'] == 0 ? lang('log.disabled_role', ['id' => $data['id']]) : lang('log.enabled_role', ['id' => $data['id']]);
            // 更新成功，写入日志
            // $this->serviceSystem->setLog(SUCCESS, 'info', lang('log.role_state'), $status);
            // 返回保存结果和角色信息
            return $this->json(SUCCESS, lang('role.update_role_status_success'), $data);
        });
    }
    
    /**
     * 分配角色权限
     * @param  array $data 包含 role_ids 和 menu_ids 两个字段
     * @return array       返回是否分配成功
     */
    public function allotRole(array $data)
    {
        return $this->tryCatch(function() use ($data) {
            // 遍历 role_ids，分别为每个角色分配权限。
            foreach ($data['role_ids'] as $role_id)
            {
                // 根据 role_id 查找对应的 Role 模型。
                $role = $this->modelSystemRole->find($role_id);
                // 为Role模型新增属性值并保存
                $role->data_type = $data['data_type'] ?? '';
                $role->dept_list = json_encode($data['dept_list']) ?? [];
                $role->grid_list = json_encode($data['grid_list']) ?? [];
                $role->dashboard = $data['dashboard'];
                $role->save();
                // 根据 role_id 查找对应的 Auth 模型。
                $auth = $role->auth;
                // 修改 Auth 模型的 role_id 和 menu_id_list 属性。
                $auth->role_id = $role_id;
                $auth->menu_id_list = json_encode($data['menu_ids']);
                $auth->save();
            }
            // 分配成功，写入日志
            // $this->serviceSystem->setLog(SUCCESS, 'info', lang('log.role_allot_auth'), lang('log.role_allot_for', ['id' => implode(',',$data['role_ids'])]));
            // 返回删除成功的信息和状态
            return $this->json(SUCCESS, lang('role.allot_role_auth_success'));
        });
    }

    /**
     * 以事务方式删除多个角色及其所有子孙角色。
     * @param array $data 待删除角色ID列表
     * @return JsonResponse
     * @throws \think\db\exception\PDOException
     * @throws \Throwable
     */
    public function deleteRole(array $data)
    {
        return $this->tryCatch(function() use ($data) {
            // 遍历 ids，分别删除对应角色及其关联的权限。
            foreach ($data['ids'] as $role_id) {
                // 根据角色 ID 查找对应的 Role 模型。
                $role = $this->modelSystemRole->find($role_id);
                if ($role) {
                    // 如果找到了对应角色，则删除其关联的 Auth 模型和自身。
                    $role->auth()->delete();
                    $role->delete();
                }
                // 获取所有包含指定角色 ID 的用户
                $users = $this->modelSystemUser->where('JSON_CONTAINS(role_list, :role_id)', ['role_id' => $role_id])->column('id, role_list');
                if ($users) {
                    foreach ($users as $user) {
                        // 将 JSON 类型的字符串转换为 PHP 数组
                        $role_list = json_decode($user['role_list'], true);
                        if (!$role_list || !is_array($role_list)) {
                            // 如果 role_list 不是一个合法的 JSON 数组，则跳过当前循环
                            continue;
                        }
                        // 过滤数组中的元素
                        $filtered_role_list = array_values(array_filter($role_list, function($value) use ($role_id) {
                            return $value != $role_id;
                        }));
                        // 更新数据库中的 role_list 字段
                        $this->modelSystemUser->where('id', $user['id'])->update(['role_list' => json_encode($filtered_role_list)]);
                    }
                }
            }
            // 删除成功，写入日志
            // $this->serviceSystem->setLog(SUCCESS, 'info', lang('log.role_delete'), lang('log.role_delete_for', ['id' => implode(',',$data['ids'])]));
            // 返回删除成功的信息和状态
            return $this->json(SUCCESS, lang('role.delete_role_success'));
        });
    }

    /**
     * 根据角色ID列表获取角色名称
     * @param array $role_list 角色ID列表
     * @return string 角色名称，使用逗号分隔
     */
    public function getRolesName(array $role_list): string
    {
        // 通过 Role 模型查询角色列表
        $roles = $this->modelSystemRole->whereIn('id', $role_list)->select();
        return $roles->isEmpty() ? '' : implode(',', $roles->column('name'));
    }
}